# -*- coding: utf-8 -*-
"""
HaaS506 RTU 主程序
简化版本 - 单片机适配的主程序
"""

import utime
import gc

# 导入RTU模块
import rtu_config
import rtu_system
import rtu_network
import rtu_mqtt
import rtu_modbus
import rtu_gpio
import rtu_ttl
import rtu_storage
import rtu_data
import rtu_time
import rtu_ota
import rtu_adc
import rtu_dispatch
import rtu_warning


class RTUApplication:
    """RTU应用程序"""

    def __init__(self):
        self.version = "2.0.0"
        self.running = False
        self.loop_count = 0

        # 运行间隔
        self.intervals = {}

        # 初始化标志
        self.initialized = False

        # 网络恢复相关
        self.last_network_recovery_check = 0
        self.last_mqtt_recovery_check = 0
        self.last_scheduled_reboot_check = 0

        # 基于时间的任务触发记录
        self.last_data_collection_time = 0
        self.last_data_upload_time = 0
        self.last_system_monitor_time = 0
        self.last_time_sync_time = 0
        self.last_network_check_time = 0
        self.last_ota_check_time = 0
        self.first_data_collected = False  # 标记是否已经进行了首次采集
        self.last_status_report_time = 0
        self.last_memory_cleanup_time = 0

        # 启动时间（使用单调时间）
        self.startup_time = utime.time()
        self.startup_ticks = utime.ticks_ms()  # 使用ticks作为备份

    def initialize(self):
        """初始化系统"""
        print("=== HaaS506 RTU Starting ===")

        try:
            # 1. 初始化配置
            if not rtu_config.init():
                print("[MAIN] Config initialization failed")
                return False
            self.version = rtu_config.get_config("system.version", self.version)
            print("=== system Version: {}".format(self.version))
            print("=== device_sn: {}".format(rtu_config.get_device_sn()))

            # 1.5 获取并显示device_sn（不重复保存）
            device_sn = rtu_config.get_device_sn()
            print("[MAIN] Device SN: {}".format(device_sn))
            # 注释掉重复的保存操作，避免启动时文件系统冲突
            # if device_sn and device_sn != "unknown" and device_sn != 10000 and device_sn != "10000":
            #     rtu_config.save_device_sn_persistent(device_sn)

            # 2. 获取运行间隔
            self.intervals = rtu_config.get_intervals()
            print("[MAIN] Intervals: {}".format(self.intervals))

            # 3. 初始化系统模块
            if not rtu_system.init():
                print("[MAIN] System initialization failed")
                return False

            # 4. 初始化存储
            if not rtu_storage.init():
                print("[MAIN] Storage initialization failed")
                return False

            # 5. 初始化GPIO
            if not rtu_gpio.init():
                print("[MAIN] GPIO initialization failed")
                return False

            # 6. 初始化TTL
            if not rtu_ttl.init():
                print("[MAIN] TTL initialization failed")
                return False

            # 7. 初始化网络
            if not rtu_network.init():
                print("[MAIN] Network initialization failed")
                return False

            # 8. 初始化MQTT
            if not rtu_mqtt.init():
                print("[MAIN] MQTT initialization failed")
                return False

            # 9. 初始化Modbus
            if not rtu_modbus.init():
                print("[MAIN] Modbus initialization failed")
                return False

            # 10. 初始化ADC
            if not rtu_adc.init():
                print("[MAIN] ADC initialization failed")
                return False

            # 11. 初始化时间模块
            if not rtu_time.init():
                print("[MAIN] Time module initialization failed")
                return False

            # 12. 初始化OTA
            if not rtu_ota.init():
                print("[MAIN] OTA initialization failed")
                return False

            # 13. 初始化命令调度
            if not rtu_dispatch.init():
                print("[MAIN] Command dispatch initialization failed")
                return False

            # 14. 初始化数据服务
            if not rtu_data.init():
                print("[MAIN] Data service initialization failed")
                return False

            # 15. 初始化预警模块
            if not rtu_warning.init():
                print("[MAIN] Warning module initialization failed")
                return False

            # 17. 设置MQTT控制回调
            rtu_mqtt.set_control_callback(self._handle_mqtt_control)

            # 18. 注册网络恢复回调
            rtu_network.register_recovery_callback(rtu_mqtt.on_network_recovery)

            # 19. 设置LED状态
            rtu_gpio.set_state_led_mode("fast_blink")  # 启动中
            rtu_gpio.set_net_led_mode("fast_blink")  # 网络连接中

            # 20. 点亮系统运行指示灯（relay1）
            rtu_gpio.flash_startup_indicator()  # 闪烁后保持点亮

            self.initialized = True
            print("=== System Initialized ===")

            return True

        except Exception as e:
            print("[MAIN] Initialization error: {}".format(e))
            return False

    def run(self):
        """运行主循环"""
        if not self.initialize():
            print("[MAIN] System initialization failed")
            return

        self.running = True
        rtu_config.g_system_status = "running"

        # 尝试连接网络
        self._connect_network()

        print("=== System Running ===")
        print("rom Version: {}".format(rtu_config.get_config("system.version")))

        try:
            while self.running:
                self.loop_count += 1

                # 处理TTL命令（总是需要处理，以便检测连接状态）
                rtu_ttl.process_commands()

                # 检查是否处于配置模式
                if rtu_ttl.is_config_mode():
                    # 配置模式下，只处理基本功能
                    # 更新LED状态（保持快闪）
                    rtu_gpio.update_leds()

                    # 发送配置模式状态
                    rtu_ttl.send_config_mode_status()

                    # 主循环延时
                    utime.sleep(0.1)  # 配置模式下更短的延时，提高响应速度
                    continue

                # === 以下是正常模式的操作 ===

                # 处理MQTT消息（每秒调用，内部有5秒间隔控制）
                rtu_mqtt.process_loop()

                # 更新断电报警（relay1闪烁，中断已处理检测）
                rtu_gpio.update_power_alarm()

                # 检查电流预警
                rtu_warning.check_current_warning()

                # 更新LED状态
                self._update_led_status()

                # 获取当前时间（使用实际时间而非循环计数）
                current_time = utime.time()

                # 网络检查 - 基于时间（如果网络断开，增加检查频率）
                network_check_interval = self.intervals.get("network_check", 150)
                if not rtu_config.g_network_ready:
                    # 网络断开时，每30秒检查一次
                    network_check_interval = 30
                
                if current_time - self.last_network_check_time >= network_check_interval:
                    self._check_network()
                    self.last_network_check_time = current_time

                # 时间同步检查 - 基于时间
                if current_time - self.last_time_sync_time >= self.intervals.get(
                    "time_sync", 600
                ):
                    self._sync_time()
                    self.last_time_sync_time = current_time

                # OTA更新检查 - 基于时间
                if current_time - self.last_ota_check_time >= 3600:  # 每小时检查一次
                    self._check_ota_update()
                    self.last_ota_check_time = current_time

                # 数据采集 - 对齐到整分钟
                collection_interval = self.intervals.get("data_collection", 60)

                # 如果间隔是60秒的倍数，对齐到特定的分钟点
                if collection_interval % 60 == 0:
                    # 计算间隔分钟数
                    interval_minutes = collection_interval // 60

                    # 获取当前时间的本地时间
                    tm = utime.localtime(current_time)
                    current_minute = tm[4]  # 当前分钟
                    current_second = tm[5]  # 当前秒

                    # 计算应该采集的分钟点（0, 5, 10, 15, 20, 25, 30, 35, 40, 45, 50, 55等）
                    # 例如：interval=300秒(5分钟)时，采集点为0,5,10,15,20,25,30,35,40,45,50,55
                    # 例如：interval=600秒(10分钟)时，采集点为0,10,20,30,40,50
                    aligned_minute = (
                        current_minute // interval_minutes
                    ) * interval_minutes

                    # 判断是否应该采集
                    should_collect = False

                    # 如果当前分钟正好是对齐的分钟，且在前2秒内
                    if current_minute == aligned_minute and current_second < 2:
                        should_collect = True

                    # 如果是首次采集
                    if not self.first_data_collected:
                        # 首次运行时，立即采集一次
                        print("[MAIN] First run, collecting data immediately")
                        self._collect_data()
                        self.first_data_collected = True
                        # 不设置 last_data_collection_time，保持为0
                        # 这样可以继续正常的对齐逻辑

                    # 正常的对齐点采集逻辑
                    if should_collect:
                        print(
                            "[MAIN-DEBUG] Data collection at: {:02d}:{:02d}:{:02d} (aligned to {} min intervals)".format(
                                tm[3], tm[4], tm[5], interval_minutes
                            )
                        )
                        self._collect_data()
                        self.last_data_collection_time = current_time
                    
                    # 检查是否已经超过了采集间隔（防止漏采）
                    elif (
                        self.last_data_collection_time > 0 and
                        current_time >= self.last_data_collection_time + collection_interval - 2
                    ):
                        # 如果已经超过间隔时间，检查是否在对齐的分钟
                        if (
                            current_minute % interval_minutes == 0
                            and current_second < 2
                        ):
                            print(
                                "[MAIN-DEBUG] Catch-up collection at: {:02d}:{:02d}:{:02d}".format(
                                    tm[3], tm[4], tm[5]
                                )
                            )
                            self._collect_data()
                            self.last_data_collection_time = current_time
                else:
                    # 非60秒倍数的间隔，使用原来的逻辑
                    # 如果是首次采集，立即执行
                    if not self.first_data_collected:
                        print("[MAIN] First run, collecting data immediately (non-aligned interval)")
                        self._collect_data()
                        self.first_data_collected = True
                        self.last_data_collection_time = current_time
                    elif (
                        current_time - self.last_data_collection_time
                        >= collection_interval
                    ):
                        print(
                            "[MAIN-DEBUG] Data collection triggered at time={}, interval={}".format(
                                current_time, collection_interval
                            )
                        )
                        self._collect_data()
                        self.last_data_collection_time = current_time

                # 数据上传 - 基于时间
                if current_time - self.last_data_upload_time >= self.intervals.get(
                    "mqtt_upload", 30
                ):
                    self._upload_data()
                    self.last_data_upload_time = current_time

                # 系统监控 - 基于时间
                if current_time - self.last_system_monitor_time >= self.intervals.get(
                    "system_monitor", 60
                ):
                    self._system_monitor()
                    self.last_system_monitor_time = current_time

                # 状态报告 - 基于时间
                if current_time - self.last_status_report_time >= 300:
                    self._report_status()
                    self.last_status_report_time = current_time

                # 网络恢复机制检查
                if self.loop_count % 30 == 0:  # 每30秒检查一次
                    self._check_network_recovery()

                # MQTT恢复机制检查
                if self.loop_count % 15 == 0:  # 每15秒检查一次，更快恢复
                    self._check_mqtt_recovery()

                # 定时重启检查
                if self.loop_count % 300 == 0:  # 每5分钟检查一次
                    self._check_scheduled_reboot()

                # 内存清理 - 基于时间
                if current_time - self.last_memory_cleanup_time >= 300:
                    self._cleanup_memory()
                    self.last_memory_cleanup_time = current_time

                # 重置计数器
                if self.loop_count >= 86400:  # 24小时
                    self.loop_count = 0

                # 主循环延时
                utime.sleep(1)

        except KeyboardInterrupt:
            print("[MAIN] System interrupted")
        except Exception as e:
            print("[MAIN] System error: {}".format(e))
            rtu_config.g_system_status = "error"

            # 保存错误信息
            rtu_storage.save_system_error(str(e))
        finally:
            self.shutdown()

    def _connect_network(self):
        """连接网络"""
        print("[MAIN] Connecting to network...")

        if rtu_network.connect_network():
            print("[MAIN] Network connected")
            rtu_gpio.set_net_led_mode("slow_blink")

            # 连接MQTT
            utime.sleep(2)
            if rtu_mqtt.connect():
                print("[MAIN] MQTT connected")
                rtu_gpio.set_net_led_mode("on")

                # 连接成功后同步时间
                if rtu_time.sync_time():
                    print("[MAIN] Time synchronized")
                else:
                    print("[MAIN] Time sync failed")
            else:
                print("[MAIN] MQTT connection failed")
        else:
            print("[MAIN] Network connection failed")

    def _check_network(self):
        """检查网络状态"""
        try:
            # 检查网络连接
            if not rtu_network.is_connected():
                print("[MAIN] Network disconnected, reconnecting...")
                rtu_gpio.set_net_led_mode("fast_blink")

                # 限制重连尝试次数，防止死循环
                max_retries = 5
                retry_count = 0

                while retry_count < max_retries:
                    if rtu_network.connect_network():
                        rtu_gpio.set_net_led_mode("slow_blink")
                        # 重新连接MQTT
                        if rtu_mqtt.connect():
                            rtu_gpio.set_net_led_mode("on")
                        break
                    else:
                        retry_count += 1
                        print(
                            "[MAIN] Network reconnect attempt {}/{} failed".format(
                                retry_count, max_retries
                            )
                        )
                        if retry_count < max_retries:
                            utime.sleep(2)  # 递增延迟

                if retry_count >= max_retries:
                    print(
                        "[MAIN] Network reconnection failed after {} attempts".format(
                            max_retries
                        )
                    )

            # 检查MQTT连接
            elif rtu_config.g_network_ready and not rtu_config.g_mqtt_connected:
                print("[MAIN] MQTT disconnected, reconnecting...")

                # 限制MQTT重连尝试次数
                max_mqtt_retries = 3
                mqtt_retry_count = 0

                while mqtt_retry_count < max_mqtt_retries:
                    if rtu_mqtt.connect():
                        rtu_gpio.set_net_led_mode("on")
                        break
                    else:
                        mqtt_retry_count += 1
                        print(
                            "[MAIN] MQTT reconnect attempt {}/{} failed".format(
                                mqtt_retry_count, max_mqtt_retries
                            )
                        )
                        if mqtt_retry_count < max_mqtt_retries:
                            utime.sleep(1)

        except Exception as e:
            print("[MAIN] Network check error: {}".format(e))

    def _check_network_recovery(self):
        """检查网络恢复机制"""
        try:
            current_time = utime.time()

            # 首先检查网络是否真的断开了
            if not rtu_network.is_connected():
                # 网络断开，尝试恢复
                if current_time - self.last_network_recovery_check > 60:  # 1分钟检查一次
                    print("[MAIN] Network disconnected, attempting recovery...")
                    
                    # 尝试正常重连
                    if rtu_network.connect_network():
                        print("[MAIN] Network recovery successful")
                        rtu_gpio.set_net_led_mode("slow_blink")
                        # 重新连接MQTT
                        if rtu_mqtt.connect():
                            rtu_gpio.set_net_led_mode("on")
                            print("[MAIN] MQTT reconnected after network recovery")
                    else:
                        print("[MAIN] Network recovery failed")
                    
                    self.last_network_recovery_check = current_time

            # 检查是否长时间断网需要强制重连
            elif rtu_network.is_long_disconnected(threshold_minutes=5):
                # 检查上次重连时间，防止频繁尝试
                if current_time - self.last_network_recovery_check > 180:  # 3分钟间隔
                    print(
                        "[MAIN] Network disconnected for >5 minutes, forcing reconnect..."
                    )

                    # 限制强制重连尝试次数
                    max_force_retries = 2
                    force_retry_count = 0

                    while force_retry_count < max_force_retries:
                        if rtu_network.force_reconnect():
                            print("[MAIN] Network force reconnect successful")
                            rtu_gpio.set_net_led_mode("slow_blink")
                            # 重新连接MQTT
                            if rtu_mqtt.connect():
                                rtu_gpio.set_net_led_mode("on")
                            break
                        else:
                            force_retry_count += 1
                            print(
                                "[MAIN] Network force reconnect attempt {}/{} failed".format(
                                    force_retry_count, max_force_retries
                                )
                            )
                            if force_retry_count < max_force_retries:
                                utime.sleep(5)  # 等待再试

                    if force_retry_count >= max_force_retries:
                        print(
                            "[MAIN] Network force reconnect failed after {} attempts".format(
                                max_force_retries
                            )
                        )

                    self.last_network_recovery_check = current_time

            # 检查是否需要重启系统（网络断开超过15分钟）
            if rtu_network.is_long_disconnected(threshold_minutes=15):
                print("[MAIN] Network disconnected for >15 minutes, system will restart")
                print("[MAIN] Saving current data before restart...")
                # 保存缓存数据
                rtu_storage.save_cache()
                # 记录重启原因
                rtu_storage.save_reboot_reason("NETWORK_LONG_DISCONNECTED")
                print("[MAIN] Restart reason: NETWORK_LONG_DISCONNECTED")
                # 延迟3秒后重启
                utime.sleep(3)
                rtu_system.restart(0)

            # 显示网络统计信息
            if current_time - self.last_network_recovery_check > 300:  # 每5分钟显示一次
                stats = rtu_network.get_connection_stats()
                print(
                    "[MAIN] Network stats: connected={}, uptime={:.1f}s, downtime={:.1f}s, retries={}, signal={}({})".format(
                        stats["connected"],
                        stats["uptime"],
                        stats["downtime"],
                        stats["retry_count"],
                        stats.get("signal_strength", -1),
                        stats.get("signal_quality", "Unknown"),
                    )
                )
                if stats.get("weak_signal", False):
                    print(
                        "[MAIN] WARNING: Weak signal detected, may experience connection issues"
                    )
                self.last_network_recovery_check = current_time

        except Exception as e:
            print("[MAIN] Network recovery check error: {}".format(e))

    def _check_mqtt_recovery(self):
        """检查MQTT恢复机制"""
        try:
            current_time = utime.time()

            # 首先检查MQTT是否断开（最重要的检查）
            if rtu_config.g_network_ready and not rtu_config.g_mqtt_connected:
                # 限制重连频率，避免过于频繁
                if current_time - self.last_mqtt_recovery_check > 10:  # 改为10秒间隔
                    print("[MAIN] MQTT disconnected, attempting immediate reconnect...")

                    # 尝试快速重连
                    if rtu_mqtt.connect():
                        print("[MAIN] MQTT reconnect successful")
                        rtu_gpio.set_net_led_mode("on")
                        self.last_mqtt_recovery_check = current_time
                        return
                    else:
                        # 如果快速重连失败，尝试强制重连
                        print(
                            "[MAIN] Quick reconnect failed, trying force reconnect..."
                        )
                        if rtu_mqtt.force_reconnect():
                            print("[MAIN] MQTT force reconnect successful")
                            rtu_gpio.set_net_led_mode("on")
                        else:
                            print("[MAIN] MQTT reconnect failed")
                            rtu_gpio.set_net_led_mode("slow_blink")

                    self.last_mqtt_recovery_check = current_time
                    return

            # 检查MQTT超时，防止频繁重连
            if rtu_mqtt.is_mqtt_timeout():
                if current_time - self.last_mqtt_recovery_check > 30:  # 改为30秒间隔
                    print("[MAIN] MQTT timeout detected, attempting reconnect...")

                    # 限制重连尝试次数
                    max_timeout_retries = 2
                    timeout_retry_count = 0

                    while timeout_retry_count < max_timeout_retries:
                        if rtu_mqtt.force_reconnect():
                            print("[MAIN] MQTT force reconnect successful")
                            break
                        else:
                            timeout_retry_count += 1
                            print(
                                "[MAIN] MQTT timeout reconnect attempt {}/{} failed".format(
                                    timeout_retry_count, max_timeout_retries
                                )
                            )
                            if timeout_retry_count < max_timeout_retries:
                                utime.sleep(3)

                    self.last_mqtt_recovery_check = current_time

            # 检查是否长时间断开
            if rtu_mqtt.is_long_disconnected(threshold_minutes=10):
                if current_time - self.last_mqtt_recovery_check > 120:  # 改为2分钟间隔
                    print(
                        "[MAIN] MQTT disconnected for >10 minutes, attempting reconnect..."
                    )

                    # 限制长时间断线重连尝试次数
                    max_long_retries = 3
                    long_retry_count = 0

                    while long_retry_count < max_long_retries:
                        if rtu_mqtt.attempt_reconnect():
                            print("[MAIN] MQTT reconnect successful")
                            break
                        else:
                            long_retry_count += 1
                            print(
                                "[MAIN] MQTT long disconnection reconnect attempt {}/{} failed".format(
                                    long_retry_count, max_long_retries
                                )
                            )
                            if long_retry_count < max_long_retries:
                                utime.sleep(5)

                    if long_retry_count >= max_long_retries:
                        print(
                            "[MAIN] MQTT reconnect failed after {} attempts, may need module restart".format(
                                max_long_retries
                            )
                        )

                    self.last_mqtt_recovery_check = current_time

            # 检查是否需要重启系统（MQTT断开超过30分钟）
            if rtu_mqtt.is_long_disconnected(threshold_minutes=30):
                print("[MAIN] MQTT disconnected for >30 minutes, system will restart")
                print("[MAIN] Saving current data before restart...")
                # 保存缓存数据
                rtu_storage.save_cache()
                # 记录重启原因
                rtu_storage.save_reboot_reason("MQTT_LONG_DISCONNECTED")
                print("[MAIN] Restart reason: MQTT_LONG_DISCONNECTED")
                # 延迟3秒后重启
                utime.sleep(3)
                rtu_system.restart(0)

            # 显示MQTT统计信息
            if current_time - self.last_mqtt_recovery_check > 300:  # 每5分钟显示一次
                stats = rtu_mqtt.get_mqtt_stats()
                print(
                    "[MAIN] MQTT stats: connected={}, uptime={:.1f}s, downtime={:.1f}s, inactive={:.1f}s".format(
                        stats["connected"],
                        stats["uptime"],
                        stats["downtime"],
                        stats["inactive_time"],
                    )
                )
                self.last_mqtt_recovery_check = current_time

        except Exception as e:
            print("[MAIN] MQTT recovery check error: {}".format(e))

    def _check_scheduled_reboot(self):
        """检查定时重启"""
        try:
            current_time = utime.time()

            # 检查是否需要定时重启
            periodic_reboot = rtu_config.get_config("system.periodic_reboot", 0)
            if periodic_reboot == 1:
                reboot_interval_hours = rtu_config.get_config(
                    "system.reboot_interval_hours", 24
                )
                reboot_interval_seconds = reboot_interval_hours * 3600

                # 使用ticks_ms计算真实运行时间，避免时间同步影响
                current_ticks = utime.ticks_ms()
                runtime_ms = utime.ticks_diff(current_ticks, self.startup_ticks)
                runtime_seconds = runtime_ms // 1000

                # 同时检查时间戳差值，防止时间同步导致的误判
                time_based_runtime = current_time - self.startup_time

                # 如果时间戳差值异常大（可能是时间同步导致），使用ticks计算的时间
                if abs(time_based_runtime - runtime_seconds) > 3600:  # 差值超过1小时
                    print(
                        "[MAIN] Time sync detected, using ticks-based runtime: {} seconds".format(
                            runtime_seconds
                        )
                    )
                    runtime = runtime_seconds
                else:
                    runtime = runtime_seconds  # 优先使用ticks计算的时间

                print(
                    "[MAIN] Runtime check: {} seconds ({:.1f} hours), reboot after {} hours".format(
                        runtime, runtime / 3600, reboot_interval_hours
                    )
                )

                if runtime > reboot_interval_seconds:
                    print(
                        "[MAIN] Scheduled reboot time reached ({} hours), rebooting...".format(
                            reboot_interval_hours
                        )
                    )
                    self._scheduled_reboot()
                    return

                # 每5分钟检查一次是否接近重启时间
                if current_time - self.last_scheduled_reboot_check > 300:
                    time_to_reboot = reboot_interval_seconds - runtime
                    if time_to_reboot < 3600 and time_to_reboot > 0:  # 1小时内重启
                        print(
                            "[MAIN] Scheduled reboot in {:.1f} minutes".format(
                                time_to_reboot / 60
                            )
                        )
                    self.last_scheduled_reboot_check = current_time

            # 检查长时间MQTT断开是否需要重启模块（此检查已在_check_mqtt_recovery中实现）
            # 移除重复的检查以避免混淆

        except Exception as e:
            print("[MAIN] Scheduled reboot check error: {}".format(e))

    def _scheduled_reboot(self):
        """执行定时重启"""
        try:
            print("[MAIN] Executing scheduled reboot...")

            # 保存重启原因
            rtu_storage.save_reboot_reason("scheduled_reboot")

            # 发送重启通知
            if rtu_config.g_mqtt_connected:
                # 使用ticks计算真实运行时间
                runtime_ms = utime.ticks_diff(utime.ticks_ms(), self.startup_ticks)
                runtime_hours = runtime_ms / (1000 * 3600)

                reboot_status = {
                    "action": "reboot",
                    "reason": "scheduled",
                    "timestamp": utime.time(),
                    "runtime_hours": runtime_hours,
                }
                rtu_mqtt.publish_status(reboot_status)
                utime.sleep(2)  # 等待消息发送

            # 关闭系统
            self.shutdown()

            # 重启
            rtu_system.restart(0)  # 立即重启

        except Exception as e:
            print("[MAIN] Scheduled reboot error: {}".format(e))

    def _sync_time(self):
        """同步时间"""
        try:
            if rtu_config.g_network_ready and rtu_time.check_sync_needed():
                if rtu_time.sync_time():
                    print("[MAIN] Time synchronized")
                else:
                    print("[MAIN] Time sync failed")
        except Exception as e:
            print("[MAIN] Time sync error: {}".format(e))

    def _check_ota_update(self):
        """检查OTA更新"""
        try:
            if rtu_config.g_network_ready and rtu_ota.is_update_needed():
                print("[MAIN] Checking for OTA updates...")
                if rtu_ota.check_update():
                    print("[MAIN] OTA update available, starting download...")
                    # 自动下载并应用更新
                    if rtu_ota.download_and_apply_update():
                        print("[MAIN] OTA update applied successfully, system will reboot")
                        # 系统会自动重启，不会到达这里
                    else:
                        print("[MAIN] OTA update download failed")
                else:
                    print("[MAIN] No OTA update available")
        except Exception as e:
            print("[MAIN] OTA update check error: {}".format(e))

    def _collect_data(self):
        """数据采集"""
        try:
            data = rtu_data.collect_data()
            if data:
                print("[MAIN] Data collected: {} fields".format(len(data)))
            else:
                print("[MAIN] Data collection failed")
        except Exception as e:
            print("[MAIN] Data collection error: {}".format(e))

    def _upload_data(self):
        """上传数据"""
        try:
            result = rtu_data.upload_data()
            if result:
                print("[MAIN] Cached data uploaded successfully")
            # 不打印误导性的失败信息，因为实时数据已经在采集时上传
        except Exception as e:
            print("[MAIN] Data upload error: {}".format(e))

    def _get_next_collection_time(self, current_time, interval_seconds):
        """计算下一个数据采集时间点"""
        if interval_seconds % 60 != 0:
            # 非60秒倍数，简单计算
            return current_time + interval_seconds

        # 60秒倍数，需要对齐
        interval_minutes = interval_seconds // 60
        tm = utime.localtime(current_time)
        current_minute = tm[4]
        current_second = tm[5]

        # 计算下一个对齐的分钟
        next_minute = ((current_minute // interval_minutes) + 1) * interval_minutes
        if next_minute >= 60:
            next_minute = next_minute % 60
            # 需要进入下一个小时
            next_time = (
                current_time + (60 - current_minute + next_minute) * 60 - current_second
            )
        else:
            next_time = (
                current_time + (next_minute - current_minute) * 60 - current_second
            )

        return next_time

    def _system_monitor(self):
        """系统监控"""
        try:
            # 检查电源告警
            if rtu_adc.check_power_warning():
                print("[MAIN] Power warning detected")

            # 电流告警已移至rtu_warning模块处理

            # 检查内存使用
            mem_free = gc.mem_free()
            if mem_free < 50000:  # 小于50KB内存告警
                print("[MAIN] Low memory warning: {}KB".format(mem_free // 1024))

        except Exception as e:
            print("[MAIN] System monitor error: {}".format(e))

    def _report_status(self):
        """报告状态"""
        try:
            status = {
                "system_status": rtu_config.g_system_status,
                "network_connected": rtu_config.g_network_ready,
                "mqtt_connected": rtu_config.g_mqtt_connected,
                "time_synced": rtu_config.g_time_synced,
                "memory_free": gc.mem_free(),
                "loop_count": self.loop_count,
                "version": self.version,
            }

            print(
                "[MAIN] Status - System: {}, Network: {}, MQTT: {}, Time: {}, Memory: {}KB".format(
                    status["system_status"],
                    status["network_connected"],
                    status["mqtt_connected"],
                    status["time_synced"],
                    status["memory_free"] // 1024,
                )
            )

            # 显示下一个数据采集时间
            collection_interval = self.intervals.get("data_collection", 60)
            if collection_interval % 60 == 0:
                current_time = utime.time()
                next_collection = self._get_next_collection_time(
                    current_time, collection_interval
                )
                next_tm = utime.localtime(next_collection)
                print(
                    "[MAIN] Next data collection at: {:02d}:{:02d}:00 (every {} minutes)".format(
                        next_tm[3], next_tm[4], collection_interval // 60
                    )
                )

            # 通过MQTT发送状态
            if rtu_config.g_mqtt_connected:
                rtu_mqtt.publish_status(status)

        except Exception as e:
            print("[MAIN] Status report error: {}".format(e))

    def _cleanup_memory(self):
        """清理内存"""
        try:
            gc.collect()
            mem_free = gc.mem_free()
            print("[MAIN] Memory cleaned: {}KB free".format(mem_free // 1024))
        except Exception as e:
            print("[MAIN] Memory cleanup error: {}".format(e))

    def _update_led_status(self):
        """更新LED状态"""
        try:
            # 更新系统LED
            if rtu_config.g_system_status == "running":
                rtu_gpio.set_state_led_mode("slow_blink")
            elif rtu_config.g_system_status == "error":
                rtu_gpio.set_state_led_mode("fast_blink")

            # 更新网络LED
            if rtu_config.g_mqtt_connected:
                rtu_gpio.set_net_led_mode("on")
            elif rtu_config.g_network_ready:
                rtu_gpio.set_net_led_mode("slow_blink")
            else:
                rtu_gpio.set_net_led_mode("fast_blink")

            # 执行LED更新
            rtu_gpio.update_leds()

        except Exception as e:
            print("[MAIN] LED update error: {}".format(e))

    def _handle_mqtt_control(self, message):
        """处理MQTT控制消息"""
        try:
            print("[MAIN] Received control message: {}".format(message))

            # 使用统一的命令调度器处理MQTT命令
            result = rtu_dispatch.process_mqtt_command(message)

            print("[MAIN] Command result: {}".format(result["status"]))

            # 特殊命令处理
            if message.get("command") == "reboot" or message.get("action") == "reboot":
                # 重启命令会在dispatch中处理，这里只需要记录
                print("[MAIN] Reboot command received and processed")

        except Exception as e:
            print("[MAIN] Control message error: {}".format(e))

    def shutdown(self):
        """关闭系统"""
        print("=== System Shutdown ===")
        self.running = False
        rtu_config.g_system_status = "shutdown"

        # 保存系统时间
        rtu_storage.save_system_time()

        # 增加重启次数
        rtu_storage.increment_reboot_count()

        # 关闭网络连接
        rtu_network.disconnect_network()

        # 关闭MQTT连接
        rtu_mqtt.disconnect()

        # 关闭LED
        rtu_gpio.set_state_led_mode("off")
        rtu_gpio.set_net_led_mode("off")

        # 关闭系统运行指示灯
        rtu_gpio.set_relay(1, False)

        print("System shutdown completed")


def test_collection_alignment():
    """测试数据采集时间对齐"""
    print("=== Testing Collection Time Alignment ===")

    # 测试不同的间隔
    test_intervals = [60, 300, 600, 900]  # 1分钟, 5分钟, 10分钟, 15分钟

    # 测试不同的当前时间
    test_times = [
        (9, 59),  # 09:59
        (10, 0),  # 10:00
        (10, 1),  # 10:01
        (14, 59),  # 14:59
        (15, 0),  # 15:00
        (15, 1),  # 15:01
        (19, 59),  # 19:59
        (20, 0),  # 20:00
        (20, 1),  # 20:01
    ]

    for interval in test_intervals:
        print("\nInterval: {} seconds ({} minutes)".format(interval, interval // 60))
        interval_minutes = interval // 60

        for hour, minute in test_times:
            # 模拟当前时间
            current_minute = minute
            current_second = 0

            # 计算对齐的分钟
            aligned_minute = (current_minute // interval_minutes) * interval_minutes
            should_collect = current_minute == aligned_minute

            # 计算下一个采集时间
            next_minute = ((current_minute // interval_minutes) + 1) * interval_minutes
            if next_minute >= 60:
                next_minute = next_minute % 60

            print(
                "  {:02d}:{:02d} -> aligned: {:02d}:00, collect: {}, next: {:02d}:00".format(
                    hour,
                    minute,
                    aligned_minute,
                    "YES" if should_collect else "NO",
                    next_minute,
                )
            )


def main():
    """主函数"""
    app = RTUApplication()
    app.run()


if __name__ == "__main__":
    main()
